home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / extensions / samples / lens.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  29KB  |  1,130 lines

  1. /*
  2.  * Copyright (c) 1994 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  *  lens - Roam around a very large image using textures tiles.
  26.  *
  27.  *  Demonstrates the use of subtexture and texture color table extensions.
  28.  *
  29.  *  $Revision: 1.1 $
  30.  */
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <bstring.h>
  35. #include <math.h>
  36. #include <GL/glu.h>
  37. #include <GL/gl.h>
  38. #include <GL/glx.h>
  39. #include <X11/keysym.h>
  40. #include <gl/image.h>
  41. #include "xwindow.h"
  42. #include "util.h"
  43.  
  44. #if!defined(GL_EXT_subtexture) || !defined(GL_EXT_abgr)
  45. BOTH EXT_subtexture and EXT_abgr must be defined
  46. #else
  47.  
  48. /* set to 1 for debug.. slower, but includes error checking */
  49. #define DEBUG 0
  50.  
  51. /* a word the size of 4 bytes (e.g. an RGBA pixel) */
  52. typedef unsigned int u_int32;
  53.  
  54. typedef struct tileimg {
  55.     int xsize, ysize;
  56.     int xtiles, ytiles;
  57.     int tilexsize, tileysize;
  58.     u_int32 **tiles;
  59. } tileimg; 
  60.  
  61. tileimg *img = NULL;
  62.  
  63. #define GETTILE(IMG,TX,TY) ((IMG)->tiles[(TY)*(IMG)->xtiles+(TX)])
  64.  
  65. #define MAXWIDTH    (4*4096)
  66.  
  67. /* size of the physical texture */
  68. #define  TEX_SIZE_S   1024
  69. #define  TEX_SIZE_T   1024
  70.  
  71. int Lminx = -TEX_SIZE_S; 
  72. int Lmaxx = -TEX_SIZE_S; 
  73. int Lminy = -TEX_SIZE_T;
  74. int Lmaxy = -TEX_SIZE_T;
  75.  
  76. unsigned int    tileXSize = 64;
  77. unsigned int    tileYSize = 64;
  78.  
  79. long winxsize, winysize;
  80. int xorg, yorg;
  81.  
  82. float myangle = 0;
  83. float zoom = 1;
  84. GLboolean useTct;
  85.  
  86. u_int32 *bgdtile = NULL;
  87. Display *dpy;
  88. Window win;
  89.  
  90. tileimg *readTiles();
  91. void changeTct(void);
  92. void changeModel(void);
  93. void rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
  94.                      unsigned short *bbuf, u_int32 *lbuf,int xsize);
  95. void processEvents(void);
  96. void makeMesh0(float x0, float x1, float y0, float y1,
  97.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  98. void makeMesh1(float x0, float x1, float y0, float y1,
  99.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  100. void makeMesh2(float x0, float x1, float y0, float y1,
  101.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  102. void makeMesh3(float x0, float x1, float y0, float y1,
  103.                float s0, float s1, float t0, float t1, float z, int nx,int ny);
  104. void makeTable1(void);
  105. void makeTable2(void);
  106. void makeTable3(void);
  107. void makeTable4(void);
  108.  
  109. void drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize);
  110. void makeRgbBgdTile(void);
  111. void makeRgbaBgdTile(void);
  112. void applyRgbaBgd(tileimg *img);
  113. tileimg *readTiles(IMAGE *image, int tilexsize, int tileysize);
  114.  
  115. #if DEBUG
  116. void chkError(char *msg);
  117. #else
  118. #define chkError
  119. #endif
  120. void usage(char *name, int exitStatus);
  121.  
  122. void
  123. main(int argc, char **argv)
  124. {
  125.     GLXContext ctx;
  126.     int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, None};
  127.  
  128.     if (argc < 2)
  129.         usage(argv[0], EXIT_FAILURE);
  130.     if (argv[1][0] == '-' && argv[1][1] == 'h')
  131.         usage(argv[0], EXIT_SUCCESS);
  132.         
  133.     winxsize = winysize = 768;
  134.     createWindowAndContext(&dpy, &win, &ctx, 0, 0, winxsize, winysize,
  135.                            GL_TRUE, NULL, visualAttr, "lens");
  136.     /* Change the event mask to watch for motion and button release as well */
  137.     XSelectInput(dpy,win, ExposureMask | StructureNotifyMask | KeyPressMask |
  138.                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
  139.     XFlush(dpy);
  140.     glClear(GL_COLOR_BUFFER_BIT);
  141.     glXSwapBuffers(dpy, win);
  142.  
  143.     /*
  144.      *    check for required extensions.
  145.      *    we know an RE/REC/REV with "abgr" has limited "subtexture" support,
  146.      *    but doesn't advertise it.
  147.      */
  148.     if (!getExtension("GL_EXT_subtexture") &&
  149.     (strncmp("RE",glGetString(GL_RENDERER),2) ||
  150.          !getExtension("GL_EXT_abgr"))) {
  151.     fprintf(stderr,"Sorry, EXT_subtexture required.\n");
  152.     exit(EXIT_FAILURE);
  153.     }
  154.  
  155. #if defined(GL_SGI_texture_color_table)
  156.     if (!(useTct = getExtension("GL_SGI_texture_color_table"))) {
  157.         /*
  158.          * HACK - texture color table is not formally advertised.
  159.          * Try using it anyhow.
  160.          */
  161.     glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
  162.         if (glGetError() == GL_NO_ERROR) {
  163.             fprintf(stderr, "Assuming SGI_texture_color_table supported but not\
  164.  advertised\n");
  165.             useTct = GL_TRUE;
  166.         }
  167.     } else
  168.         useTct = GL_TRUE;
  169.     if (!useTct)
  170.         fprintf(stderr,
  171.                 "SGI_texture_color_table is not supported by this renderer\n");
  172. #else
  173.     useTct = GL_FALSE;
  174. #endif
  175.  
  176.     {
  177.         IMAGE *image = iopen(argv[1], "r");
  178.         int iclose(IMAGE *);
  179.         
  180.     if (!image) {
  181.         fprintf(stderr,"%s: can't open input file %s\n",argv[0], argv[1]);
  182.         exit(EXIT_FAILURE);
  183.     }
  184.     if (argc > 2) {
  185.             tileXSize = atoi(argv[2]);
  186.             tileYSize = argc > 3 ? atoi(argv[3]) : tileXSize;
  187.     }
  188.     fprintf(stderr,"TILE{XSIZE, YSIZE} = %d,%d\n",tileXSize,tileYSize);
  189.         img = readTiles(image, tileXSize, tileYSize);
  190.     (void) iclose(image);
  191.     }
  192.  
  193.     makeRgbaBgdTile();
  194.     applyRgbaBgd(img);
  195.  
  196.     glMatrixMode(GL_TEXTURE);
  197.     glLoadIdentity();
  198.     glTranslatef(0.5,0.5,0.0);
  199.     glScalef(.61,.61,1.);
  200.     glMatrixMode(GL_PROJECTION);
  201.     glLoadIdentity();
  202.     gluPerspective(90.,1.,.1,10.);
  203.     glMatrixMode(GL_MODELVIEW);
  204.     glLoadIdentity();
  205.     glTranslatef(0.,0.,-1.5);
  206.  
  207.     glEnable(GL_TEXTURE_2D);
  208.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  209.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  210.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); /*default*/
  211.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); /*default*/
  212.  
  213.     glTexImage2D(GL_TEXTURE_2D,0,GL_RGB5_EXT,TEX_SIZE_S,TEX_SIZE_T,0,
  214.                  GL_RGBA,GL_UNSIGNED_BYTE,NULL);
  215. #if DEBUG
  216.     chkError("after glTexImage2D");
  217. #endif
  218.  
  219.     xorg = -(img->xsize/2.0 - TEX_SIZE_S/2.0);
  220.     yorg = -(img->ysize/2.0 - TEX_SIZE_T/2.0);
  221.  
  222.     makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  223.  
  224.     drawTiles(img,-xorg,-yorg,winxsize,winysize);
  225.     glXSwapBuffers(dpy, win);
  226.  
  227.     chkError("before processEvents");
  228.  
  229.     processEvents();
  230. }
  231.  
  232. void
  233. usage(char *name, int exitStatus)
  234. {
  235.     fprintf(stderr,
  236.             "usage: %s [-h (for help)] inimage [[tileWidthAndHeight] or\
  237.  [tileWidth tileHeight]]\n", name);
  238.     fprintf(stderr,
  239.             "\tInteractively, `h/?' keys provide description of interface\n");
  240.     exit(exitStatus);
  241. }
  242.  
  243. void
  244. processEvents(void)
  245. {
  246.     int lx, ly, mx, my;
  247.     float fx, fy;
  248.     int i;
  249.     int leftdown = 0;
  250.  
  251.     while(1) {
  252.     int needredraw;
  253.     XEvent event;
  254.     XNextEvent(dpy, &event);
  255.     switch (event.type) {
  256.           case Expose: /* window needs to be redrawn */
  257.           {
  258.               /* skip all but last "Expose" event (X often sends 2 or 3) */
  259.               if (((XExposeEvent*) &event)->count == 0) {
  260.                   drawTiles(img,-xorg,-yorg,winxsize,winysize);
  261.                   glXSwapBuffers(dpy, win);
  262.               }
  263.           }
  264.           break;
  265.           case ConfigureNotify: /* window resize (or a move) occurred */
  266.           {
  267.               winxsize = ((XConfigureEvent*) &event)->width;
  268.               winysize = ((XConfigureEvent*)&event)->height;
  269.               glViewport(0, 0, winxsize, winysize);
  270.               drawTiles(img,-xorg,-yorg,winxsize,winysize);
  271.               glXSwapBuffers(dpy, win);
  272.           }
  273.           break;
  274.           case KeyPress:
  275.           {
  276.               KeySym keysym;
  277.  
  278.               (void) XLookupString(&event.xkey, NULL, 0, &keysym, 0);
  279.               switch (keysym) {
  280.                 case XK_Escape: /* ESC key */
  281.                   exit(EXIT_SUCCESS);
  282.                   break;
  283.                 case XK_Up: /* up arrow */
  284.                   zoom -= .02;
  285.                   if (zoom < 0.02) zoom = 0.02;
  286.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  287.                   glXSwapBuffers(dpy, win);
  288.                   break;
  289.                 case XK_Down: /* down arrow */
  290.                   zoom += .02;
  291.                   if (zoom > 1) zoom = 1;
  292.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  293.                   glXSwapBuffers(dpy, win);
  294.                   break;
  295.                 case XK_w:
  296.                   changeModel();
  297.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  298.                   glXSwapBuffers(dpy, win);
  299.                   break;
  300.                 case XK_l: /* left arrow */
  301.                   changeTct();
  302.                   chkError("after changeTct");
  303.                   drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  304.                   glXSwapBuffers(dpy, win);
  305.                   break;
  306.                 case XK_h:
  307.                 case XK_H:
  308.                 case XK_question:
  309.                   printf("\tUp/Down arrow - zoom in/out\n");
  310.                   printf("\tRight arrow\n");
  311.                   printf("\tl - cycle through texture lookup tables\n");
  312.                   printf("\tw - cycle through warping effects\n");
  313.                   printf("\tLeft mouse - drag image\n");
  314.                   printf("\tMiddle/Right mouse - rotate image CCW/CW\n");
  315.                   printf("\th/? - help\n");
  316.                   printf("\tEsc - quit\n");
  317.                   break;
  318.               }
  319.           }
  320.                   break;
  321.           case ButtonPress:
  322.           {
  323.               switch (((XButtonEvent *)&event)->button) {
  324.                 case 1:
  325.                   leftdown = 1;
  326.                   lx = ((XButtonEvent *)&event)->x;
  327.                   ly = ((XButtonEvent *)&event)->y;
  328.           break;
  329.                 case 2:
  330.                   do {
  331.                       myangle -= 1.0;
  332.                       if (myangle < -360.0)
  333.                           myangle += 360.0;
  334.                       drawTiles(img, -xorg, -yorg, winxsize, winysize); 
  335.                       glXSwapBuffers(dpy, win);
  336.                   } while(xGetButton(2, dpy, win));
  337.                   break;
  338.                 case 3:
  339.                   do {
  340.                       myangle += 1.0;
  341.                       if (myangle > 360.0)
  342.                           myangle -= 360.0;
  343.                       drawTiles(img,-xorg,-yorg,winxsize,winysize); 
  344.                       glXSwapBuffers(dpy, win);
  345.                   } while (xGetButton(3, dpy, win));
  346.                   break;
  347.               }
  348.           }
  349.           break;
  350.  
  351.           case MotionNotify: /* cursor moved (in window) */
  352.         /* absorb extra motion events... */
  353.         if (leftdown) {
  354.         XMotionEvent *ev = (XMotionEvent*)&event;
  355.  
  356.         while (XEventsQueued(dpy, QueuedAfterReading)) {
  357.               XEvent tev;
  358.  
  359.               XNextEvent(dpy, &tev);
  360.               if (tev.type == MotionNotify) {
  361.               ev = (XMotionEvent*)&tev;
  362.               } else {
  363.               XPutBackEvent(dpy, &tev);
  364.               break;
  365.               }
  366.         }
  367.         mx = ev->x;
  368.         my = ev->y;
  369.         if(mx != lx || my != ly) {
  370.               xorg += (mx - lx);
  371.               yorg += -(my - ly); /* in X, y is inverted (yuk) */
  372.               drawTiles(img, -xorg, -yorg, winxsize, winysize);
  373.               glXSwapBuffers(dpy, win);
  374.               lx = mx;
  375.               ly = my;
  376.         }
  377.         }
  378.           break;
  379.       case ButtonRelease:
  380.         if (((XButtonEvent *)&event)->button == 1)
  381.         leftdown = 0;
  382.         break;
  383.     }
  384. #if DEBUG
  385.     chkError("processEvents");
  386. #endif
  387.     }
  388. }
  389.  
  390.  
  391. void
  392. changeModel(void)
  393. {
  394.     static int model = 0;
  395.  
  396.     model = (model + 1) % 4;
  397.     switch (model) {
  398.       case 0:  
  399.         makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  400.         break;
  401.       case 1:  
  402.         makeMesh1(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  403.         break;
  404.       case 2:  
  405.         makeMesh3(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  406.         break;
  407.       case 3:  
  408.         makeMesh2(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
  409.         break;
  410.     }
  411. }
  412.  
  413. tileimg *
  414. readTiles(IMAGE *image, int tilexsize, int tileysize)
  415. {
  416.     int xsize, ysize, zsize;
  417.     int i, x, y, ntiles;
  418.     u_int32 *lptr;
  419.     u_int32 ***tiles;
  420.     tileimg *img;
  421.     unsigned short rbuf[MAXWIDTH];
  422.     unsigned short gbuf[MAXWIDTH];
  423.     unsigned short bbuf[MAXWIDTH];
  424.     u_int32 lbuf[MAXWIDTH];
  425.  
  426.  
  427.     xsize = image->xsize;
  428.     ysize = image->ysize;
  429.     zsize = image->zsize;
  430.  
  431.     if (image->xsize > MAXWIDTH) {
  432.     printf("cannot handle image wider than %d pixels.\n", MAXWIDTH);
  433.     exit(EXIT_FAILURE);
  434.     }
  435.  
  436.     img = (tileimg *) malloc(sizeof(tileimg));
  437.     img->xsize = xsize;
  438.     img->ysize = ysize;
  439.     img->xtiles = ((xsize-1)/tilexsize)+1;
  440.     img->ytiles = ((ysize-1)/tileysize)+1;
  441.     img->tilexsize = tilexsize;
  442.     img->tileysize = tileysize;
  443.     img->tiles =
  444.         (u_int32**) malloc(img->ytiles*img->xtiles * sizeof(u_int32*));
  445.     ntiles = img->xtiles*img->ytiles;
  446. #if DEBUG
  447.     printf("begin malloc ntile %d size %d\n",ntiles,tilexsize*tileysize*4);
  448.     printf("\t\t tilexsize,tileysize: %d %d xsize,ysize %d %d xtiles\
  449.  ytiles:%d %d\n", tilexsize,tileysize,xsize,ysize,img->xtiles,img->ytiles);
  450. #endif
  451.     for(i=0; i<ntiles; i++) {
  452.     img->tiles[i] =
  453.             (u_int32 *) malloc(tilexsize*tileysize*sizeof(u_int32));
  454.     }
  455. #if DEBUG
  456.     printf("end malloc\n");
  457. #endif
  458.     printf("Reading image..."); fflush(stdout);
  459.     for(y=0; y<ysize; y++) {
  460.         int getrow(IMAGE *image, unsigned short *buffer,
  461.                    unsigned int y, unsigned int z);
  462.         if(zsize >= 3) {
  463.         getrow(image,rbuf,y,0);
  464.         getrow(image,gbuf,y,1);
  465.         getrow(image,bbuf,y,2);
  466.         rgbToPackedRgba(rbuf,gbuf,bbuf,lbuf,xsize);
  467.     } else {
  468.         getrow(image,rbuf,y,0);
  469.         rgbToPackedRgba(rbuf,rbuf,rbuf,lbuf,xsize);
  470.     }
  471.     for(x=0; x<img->xtiles; x++) {
  472.         lptr = GETTILE(img,x,y/tileysize) + (tilexsize*(y%tileysize));
  473.         bcopy(lbuf+x*tilexsize,lptr,tilexsize*sizeof(u_int32));
  474.     }
  475.     }
  476.     printf("Done\n"); fflush(stdout);
  477.     return img;
  478. }
  479.  
  480. /*
  481.  * The following 4 procedures create meshes for the different kind of
  482.  * warping effects.
  483.  */
  484. #define MAXMESH 64
  485.  
  486. float Ml[4*2*(MAXMESH+1)*2 * (MAXMESH+1)];
  487.  
  488. void
  489. makeMesh0(float x0, float x1, float y0, float y1,
  490.           float s0, float s1, float t0, float t1, float z, int nx,int ny)
  491. {
  492.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  493.     float v;
  494.     float *mp = Ml;
  495.     
  496.     dx = (x1-x0)/nx;
  497.     dy = (y1-y0)/ny;
  498.     ds = (s1-s0)/nx;
  499.     dt = (t1-t0)/ny;
  500.     y = y0;
  501.     t = t0;
  502.     vb[2] = z;
  503.     while (y < y1) {
  504.         x = x0;
  505.         s = s0;
  506.         while(x <= x1) {
  507.             tb[0] = s; tb[1] = t;
  508.             vb[0] = x; vb[1] = y;
  509.             vb[2] = 0.0;
  510.             *mp++ = tb[0];    
  511.             *mp++ = tb[1];    
  512.             mp += 2;
  513.             *mp++ = vb[0];    
  514.             *mp++ = vb[1];    
  515.             *mp++ = vb[2];    
  516.             mp++;
  517.             tb[1] = t+dt;
  518.             vb[1] = y+dy;
  519.             vb[2] = 0.0;
  520.             *mp++ = tb[0];    
  521.             *mp++ = tb[1];    
  522.             mp += 2;
  523.             *mp++ = vb[0];    
  524.             *mp++ = vb[1];    
  525.             *mp++ = vb[2];    
  526.             mp++;
  527.             x += dx;
  528.             s += ds;
  529.         }    
  530.         y += dy;
  531.         t += dt;
  532.     }
  533. }
  534.  
  535. void
  536. makeMesh1(float x0, float x1, float y0, float y1,
  537.           float s0, float s1, float t0, float t1, float z, int nx, int ny)
  538. {
  539.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  540.     float v;
  541.     float *mp = Ml;
  542.     float N = 2.0;
  543.     float B = -1.5;
  544.     
  545.     dx = (x1-x0)/nx;
  546.     dy = (y1-y0)/ny;
  547.     ds = (s1-s0)/nx;
  548.     dt = (t1-t0)/ny;
  549.     y = y0;
  550.     t = t0;
  551.     vb[2] = z;
  552.     while (y < y1) {
  553.         x = x0;
  554.         s = s0;
  555.         while(x <= x1) {
  556.             tb[0] = s; tb[1] = t;
  557.             vb[0] = x; vb[1] = y;
  558.             v = N*N - x*x - y*y;
  559.             if (v < 0.0) v = 0.0;
  560.             vb[2] = sqrt(v) + B;
  561.             if (vb[2] < 0.) vb[2] = 0.0;
  562.             *mp++ = tb[0];    
  563.             *mp++ = tb[1];    
  564.             mp += 2;
  565.             *mp++ = vb[0];    
  566.             *mp++ = vb[1];    
  567.             *mp++ = vb[2];    
  568.             mp++;
  569.             tb[1] = t+dt;
  570.             vb[1] = y+dy;
  571.             v = N*N - x*x - (y+dy)*(y+dy);
  572.             if (v < 0.0) v = 0.0;
  573.             vb[2] = sqrt(v) + B;
  574.             if (vb[2] < 0.) vb[2] = 0.0;
  575.             *mp++ = tb[0];    
  576.             *mp++ = tb[1];    
  577.             mp += 2;
  578.             *mp++ = vb[0];    
  579.             *mp++ = vb[1];    
  580.             *mp++ = vb[2];    
  581.             mp++;
  582.             x += dx;
  583.             s += ds;
  584.         }    
  585.         y += dy;
  586.         t += dt;
  587.     }
  588. }
  589.  
  590. void
  591. makeMesh2(float x0, float x1, float y0, float y1,
  592.           float s0, float s1, float t0, float t1, float z, int nx,int ny)
  593. {
  594.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  595.     float v;
  596.     float *mp = Ml;
  597.     float N2 = 4.0;
  598.     float B2 = -3.5;
  599.     
  600.     dx = (x1-x0)/nx;
  601.     dy = (y1-y0)/ny;
  602.     ds = (s1-s0)/nx;
  603.     dt = (t1-t0)/ny;
  604.     y = y0;
  605.     t = t0;
  606.     vb[2] = z;
  607.     while (y < y1) {
  608.         x = x0;
  609.         s = s0;
  610.         while(x <= x1) {
  611.             tb[0] = s; tb[1] = t;
  612.             vb[0] = x; vb[1] = y;
  613.             v = N2*N2 - x*x - y*y;
  614.             if (v < 0.0) v = 0.0;
  615.             vb[2] = sqrt(v) + B2;
  616.             *mp++ = tb[0];    
  617.             *mp++ = tb[1];    
  618.             mp += 2;
  619.             *mp++ = vb[0];    
  620.             *mp++ = vb[1];    
  621.             *mp++ = vb[2];    
  622.             mp++;
  623.             tb[1] = t+dt;
  624.             vb[1] = y+dy;
  625.             v = N2*N2 - x*x - (y+dy)*(y+dy);
  626.             if (v < 0.0) v = 0.0;
  627.             vb[2] = sqrt(v) + B2;
  628.             *mp++ = tb[0];    
  629.             *mp++ = tb[1];    
  630.             mp += 2;
  631.             *mp++ = vb[0];    
  632.             *mp++ = vb[1];    
  633.             *mp++ = vb[2];    
  634.             mp++;
  635.             x += dx;
  636.             s += ds;
  637.         }    
  638.         y += dy;
  639.         t += dt;
  640.     }
  641. }
  642.  
  643. void
  644. makeMesh3(float x0, float x1, float y0, float y1,
  645.           float s0, float s1, float t0, float t1, float z, int nx, int ny)
  646. {
  647.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  648.     float v;
  649.     float *mp = Ml;
  650.     float N3 = 2.0;
  651.     float B3 = -1.0;
  652.     
  653.     dx = (x1-x0)/nx;
  654.     dy = (y1-y0)/ny;
  655.     ds = (s1-s0)/nx;
  656.     dt = (t1-t0)/ny;
  657.     y = y0;
  658.     t = t0;
  659.     vb[2] = z;
  660.     while (y < y1) {
  661.         x = x0;
  662.         s = s0;
  663.         while(x <= x1) {
  664.             tb[0] = s; tb[1] = t;
  665.             vb[0] = x; vb[1] = y;
  666.             v = N3*N3 - x*x - y*y;
  667.             if (v < 0.0) v = 0.0;
  668.             vb[2] = sqrt(v) + B3;
  669.             if (vb[2] < 0.) vb[2] = 0.0;
  670.             vb[2] = -vb[2];
  671.             *mp++ = tb[0];    
  672.             *mp++ = tb[1];    
  673.             mp += 2;
  674.             *mp++ = vb[0];    
  675.             *mp++ = vb[1];    
  676.             *mp++ = vb[2];    
  677.             mp++;
  678.             tb[1] = t+dt;
  679.             vb[1] = y+dy;
  680.             v = N3*N3 - x*x - (y+dy)*(y+dy);
  681.             if (v < 0.0) v = 0.0;
  682.             vb[2] = sqrt(v) + B3;
  683.             if (vb[2] < 0.) vb[2] = 0.0;
  684.             vb[2] = -vb[2];
  685.             *mp++ = tb[0];    
  686.             *mp++ = tb[1];    
  687.             mp += 2;
  688.             *mp++ = vb[0];    
  689.             *mp++ = vb[1];    
  690.             *mp++ = vb[2];    
  691.             mp++;
  692.             x += dx;
  693.             s += ds;
  694.         }    
  695.         y += dy;
  696.         t += dt;
  697.     }
  698. }
  699.  
  700. void
  701. drawMesh(int nx,int ny)
  702. {
  703.     float *mp = Ml;
  704.     int i,j;
  705.  
  706.     glColor4f(1,1,1,1);
  707.     for (i = ny+1; i; i--) {
  708.         glBegin(GL_TRIANGLE_STRIP);
  709.         for (j = nx+1; j; j--) {
  710.             glTexCoord2fv(mp);    mp += 4;
  711.             glVertex3fv(mp);    mp += 4;
  712.             glTexCoord2fv(mp);    mp += 4;
  713.             glVertex3fv(mp);    mp += 4;
  714.         }
  715.         glEnd();
  716.     }
  717. }
  718.  
  719.  
  720. void
  721. loadtile(float s, float t, int x, int y, tileimg *img)
  722. {
  723.     GLvoid *tile;
  724.  
  725.     tile = (GLvoid *) (x < 0 || x >= img->xtiles || y < 0 || y >= img->ytiles ?
  726.                        bgdtile : GETTILE(img,x,y));
  727.     glTexSubImage2DEXT(GL_TEXTURE_2D, 0, s*TEX_SIZE_S+.5, t*TEX_SIZE_T+.5,
  728.                        tileXSize, tileYSize, GL_RGBA, GL_UNSIGNED_BYTE,
  729.                        tile);
  730. #if DEBUG
  731.     chkError("after glTexSubImage2D");
  732. #endif
  733. }
  734.  
  735. void
  736. drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize)
  737. {
  738.     int minx,maxx,miny,maxy;
  739.     float s0,t0;
  740.     int x, y, first,last;
  741.  
  742.     glClear(GL_COLOR_BUFFER_BIT);
  743.  
  744.     minx = xorg < 0 ? (xorg - img->tilexsize - 1)/img->tilexsize :
  745.         xorg/img->tilexsize;
  746.     maxx = (xorg + TEX_SIZE_S)/(float) img->tilexsize - 1;
  747.     miny = yorg < 0 ? (yorg-img->tileysize-1)/img->tileysize :
  748.         yorg/img->tileysize;
  749.     maxy = (yorg + TEX_SIZE_T)/(float) img->tileysize - 1;
  750.  
  751.     /* Bring in any newly exposed tiles on the left */
  752.     if (minx < Lminx) {
  753.         for (x = minx; x < Lminx; x++) {
  754.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  755.         s0 -= (int) s0;  /* get the fractional position */
  756.          if (s0 < 0.0)
  757.         s0 += 1.0;
  758.         for (y = miny; y <= maxy; y++) {
  759.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  760.         t0 -= (int) t0;
  761.              if (t0 < 0.0)
  762.             t0 += 1.0;
  763.                 loadtile(s0, t0, x, y, img);
  764.         
  765.         }
  766.     }
  767.     first = Lminx;
  768.     } else
  769.         first = minx;
  770.  
  771.     /* Bring in newly exposed tiles on the right */
  772.     if (maxx > Lmaxx) {
  773.     x = Lmaxx > minx ? Lmaxx+1 : minx;
  774.      last = x - 1;
  775.         for (; x <= maxx; x++) {
  776.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  777.         s0 -= (int) s0;  /* get the fractional position */
  778.          if (s0 < 0.0)
  779.         s0 += 1.0;
  780.         for (y = miny; y <= maxy; y++) {
  781.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  782.         t0 -= (int) t0;
  783.              if (t0 < 0.0)
  784.             t0 += 1.0;
  785.                 loadtile(s0, t0, x, y, img);
  786.         }
  787.     }
  788.     } else
  789.         last = maxx;
  790.  
  791.     /* Bring in newly exposed tiles on the bottom */
  792.     if (miny < Lminy) {
  793.         for (y = miny; y < Lminy; y++) {
  794.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  795.         t0 -= (int) t0;  /* get the fractional position */
  796.          if (t0 < 0.0)
  797.         t0 += 1.0;
  798.         for (x = first; x <= last; x++) {
  799.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  800.                 s0 -= (int) s0;  /* get the fractional position */
  801.              if (s0 < 0.0)
  802.             s0 += 1.0;
  803.                 loadtile(s0, t0, x, y, img);
  804.         }
  805.     }
  806.     }
  807.  
  808.     /* Bring in newly exposed tiles on the top */
  809.     if (maxy > Lmaxy) {
  810.         for (y = Lmaxy+1 ; y <= maxy; y++) {
  811.         t0 = y * (tileYSize/(float) TEX_SIZE_T);
  812.         t0 -= (int) t0;  /* get the fractional position */
  813.          if (t0 < 0.0)
  814.         t0 += 1.0;
  815.         for (x = first; x <= last; x++) {
  816.         s0 = x * (tileXSize/(float) TEX_SIZE_S);
  817.                 s0 -= (int) s0;  /* get the fractional position */
  818.              if (s0 < 0.0)
  819.             s0 += 1.0;
  820.                 loadtile(s0, t0, x, y, img);
  821.         }
  822.     }
  823.     }
  824.  
  825.     Lminx = minx;
  826.     Lmaxx = maxx;
  827.     Lminy = miny;
  828.     Lmaxy = maxy;
  829.     glMatrixMode(GL_TEXTURE);
  830.     glLoadIdentity();
  831.     glTranslatef(xorg/(float) TEX_SIZE_S+0.5,yorg/(float) TEX_SIZE_T+0.5,0.0);
  832.     glRotatef(myangle, 0, 0, 1); /* z rotate */
  833.     glScalef(.63*zoom,.63*zoom,1.);
  834.     glTranslatef(-.5,-.5,0.);
  835.     glMatrixMode(GL_MODELVIEW);
  836.  
  837.     drawMesh(64,64);
  838. }
  839.  
  840.  
  841. void
  842. changeTct(void)
  843. {
  844. #if defined(GL_SGI_texture_color_table)
  845.     static int lut = 0;
  846.     
  847.     if (!useTct)
  848.         return;
  849.  
  850.     lut = (lut + 1) % 5;
  851.     if (lut == 0) {
  852.     glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
  853.         chkError("after disable TCT");
  854.         return;
  855.     }
  856.     glEnable(GL_TEXTURE_COLOR_TABLE_SGI);
  857.     chkError("after enable TCT");
  858.  
  859.     switch (lut) {
  860.     case 1: makeTable1(); break;
  861.     case 2: makeTable2(); break;
  862.     case 3: makeTable3(); break;
  863.     case 4: makeTable4(); break;
  864.     }
  865. #endif
  866. }
  867.  
  868. void
  869. makeTable1(void)
  870. {    
  871. #if defined(GL_SGI_texture_color_table)
  872.     static unsigned long table[256];
  873.     static int done = 0;
  874.     int i;
  875.     float v;
  876.     int iv;
  877.  
  878.     if (!done) {
  879.     for (i = 0; i < 256; i++){
  880.         v = i/255.0;
  881.         iv = powf(v,(float) 2.0) * 255;
  882.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv)); 
  883.     }
  884.     done = 1;
  885.     }
  886.  
  887.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  888.                     GL_RGBA, GL_UNSIGNED_BYTE, table);
  889. #endif
  890. }
  891.  
  892. void
  893. makeTable2(void)
  894. {    
  895. #if defined(GL_SGI_texture_color_table)
  896.     static unsigned long table[256];
  897.     static int done = 0;
  898.     int i;
  899.     float v;
  900.     int iv;
  901.  
  902.     if (!done) {
  903.     for (i = 0; i < 256; i++) {
  904.         v = i/255.0;
  905.         iv = powf(v,(float) 1.0) * 255;
  906.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv));
  907.     }
  908.     done = 1;
  909.     }
  910.  
  911.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  912.                     GL_RGBA, GL_UNSIGNED_BYTE, table);
  913. #endif
  914. }
  915.  
  916.  
  917. /*
  918.  *  define DLIST first time, and call it every time.
  919.  */
  920. void
  921. makeTable3(void)
  922. {    
  923. #if defined(GL_SGI_texture_color_table)
  924.     static unsigned long table[256];
  925.     static GLuint list = 0;
  926.     int i;
  927.     float v;
  928.     int iv;
  929.  
  930.     if (list == 0) {
  931.     for (i = 0; i < 256; i++){
  932.         v = i/255.0;
  933.         iv = powf(v,(float) 0.5) * 255;
  934.         table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv)); 
  935.     }
  936.         list = glGenLists(1);
  937.     glNewList(list, GL_COMPILE);
  938.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  939.                         GL_RGBA, GL_UNSIGNED_BYTE, table);
  940.     glEndList();
  941.     }
  942.  
  943.     glCallList(list);
  944. #endif
  945. }
  946.  
  947. /*
  948.  *  Create an inverting color table ("negative" effect)
  949.  *  use LUMINANCE table because R,G,B,A tables are the same.
  950.  */
  951. void
  952. makeTable4(void)
  953. {    
  954. #if defined(GL_SGI_texture_color_table)
  955.     static unsigned char table[256];
  956.     static int done = 0;
  957.     int i;
  958.  
  959.     if (!done) {
  960.     for (i = 0; i < 256; i++) {
  961.         table[i] = 255-i; 
  962.     }
  963.     done = 1;
  964.     }
  965.     glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
  966.                     GL_LUMINANCE, GL_UNSIGNED_BYTE, table);
  967. #endif
  968. }
  969.  
  970. void
  971. rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
  972.                 unsigned short *bbuf, u_int32 *lbuf, int xsize)
  973. {
  974.     char *cptr;    
  975.     int i;
  976.     
  977.     cptr = (char *) lbuf;
  978.  
  979.     for (i = xsize; i; i--) {
  980.         *cptr++ = *rbuf++;
  981.         *cptr++ = *gbuf++;
  982.         *cptr++ = *bbuf++;
  983.         *cptr++ = 0x00;
  984.     }
  985. }
  986.  
  987. /*
  988.  * "Draw" an rgb tile for the background.
  989.  */
  990. void
  991. makeRgbBgdTile(void)
  992. {
  993.     int i,j,grid;
  994.     char *ptr;
  995.  
  996.     bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32)*3/4);
  997.     grid = 8;
  998.     ptr = (char *) bgdtile;
  999.     for (i=0; i<tileYSize; i++) {
  1000.     for(j=0; j<tileXSize; j++) {
  1001.        if(i%grid == 0 || j%grid == 0) {
  1002.         *ptr++ = 0x0; *ptr++ = 0x0; *ptr++ = 0x40; 
  1003.        } else {
  1004.         *ptr++ = 0x40; *ptr++ = 0x40; *ptr++ = 0x40; 
  1005.        }
  1006.         }
  1007.     }
  1008. }
  1009.  
  1010. /*
  1011.  * "Draw" an rgba tile for the background.
  1012.  */
  1013. void
  1014. makeRgbaBgdTile(void)
  1015. {
  1016.     int i,j,grid;
  1017.     u_int32 *ptr;
  1018.  
  1019.     bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32));
  1020.     grid = 8;
  1021.     ptr = (u_int32 *) bgdtile;
  1022.     for (i=0; i<tileYSize; i++) {
  1023.     for(j=0; j<tileXSize; j++) {
  1024.        if(i%grid == 0 || j%grid == 0) {
  1025.         *ptr++ = 0x40000000;    /* red is the upper byte */
  1026.        } else {
  1027.         *ptr++ = 0x40404000;
  1028.        }
  1029.         }
  1030.     }
  1031. }
  1032.  
  1033. void
  1034. applyBgd(tileimg *img)
  1035. {
  1036.     int extras,y,x,i,j;
  1037.     char *ptr,*bgd;
  1038.  
  1039.     extras = img->xsize % img->tilexsize;
  1040.     if (extras) {
  1041.     for (y=0; y< img->ytiles; y++) {
  1042.         ptr = (char *) GETTILE(img,img->xtiles-1,y);
  1043.         bgd = (char *) bgdtile;
  1044.         for (j = 0; j< img->tileysize; j++) {
  1045.         ptr += 3*extras;        
  1046.         bgd += 3*extras;        
  1047.         for (i=extras; i< img->tilexsize; i++) {
  1048.             *ptr++ = *bgd++;        
  1049.             *ptr++ = *bgd++;        
  1050.             *ptr++ = *bgd++;        
  1051.         }
  1052.         }
  1053.     }
  1054.     }
  1055.     extras = img->ysize % img->tileysize;
  1056.     if (extras) {
  1057.     for (x=0; x< img->xtiles; x++) {
  1058.         ptr = (char *) GETTILE(img,x,img->ytiles-1);
  1059.         bgd = (char *) bgdtile;
  1060.         ptr += 3*extras* img->tilexsize;
  1061.         bgd += 3*extras* img->tilexsize;
  1062.         for (j = extras; j< img->tileysize; j++) {
  1063.         for (i=0; i< img->tilexsize; i++) {
  1064.             *ptr++ = *bgd++;        
  1065.             *ptr++ = *bgd++;        
  1066.             *ptr++ = *bgd++;        
  1067.         }
  1068.         }
  1069.     }
  1070.     }
  1071. }
  1072.  
  1073. void
  1074. applyRgbaBgd(tileimg *img)
  1075. {
  1076.     int extras,y,x,i,j;
  1077.     char *ptr,*bgd;
  1078.  
  1079.     extras = img->xsize % img->tilexsize;
  1080.     if (extras) {
  1081.     for (y=0; y< img->ytiles; y++) {
  1082.         ptr = (char *) GETTILE(img,img->xtiles-1,y);
  1083.         bgd = (char *) bgdtile;
  1084.         for (j = 0; j< img->tileysize; j++) {
  1085.         ptr += 4*extras;        
  1086.         bgd += 4*extras;        
  1087.         for (i=extras; i< img->tilexsize; i++) {
  1088.             *ptr++ = *bgd++;        
  1089.             *ptr++ = *bgd++;        
  1090.             *ptr++ = *bgd++;        
  1091.             *ptr++ = *bgd++;        
  1092.         }
  1093.         }
  1094.     }
  1095.     }
  1096.     extras = img->ysize % img->tileysize;
  1097.     if (extras) {
  1098.     for (x=0; x< img->xtiles; x++) {
  1099.         ptr = (char *) GETTILE(img,x,img->ytiles-1);
  1100.         bgd = (char *) bgdtile;
  1101.         ptr += 4*extras* img->tilexsize;
  1102.         bgd += 4*extras* img->tilexsize;
  1103.         for (j = extras; j< img->tileysize; j++) {
  1104.         for (i=0; i< img->tilexsize; i++) {
  1105.             *ptr++ = *bgd++;        
  1106.             *ptr++ = *bgd++;        
  1107.             *ptr++ = *bgd++;        
  1108.             *ptr++ = *bgd++;        
  1109.         }
  1110.         }
  1111.     }
  1112.     }
  1113. }
  1114.  
  1115. #if DEBUG
  1116. void
  1117. chkError(char *msg)
  1118. {
  1119.     GLenum err;
  1120.     char *errstr;
  1121.  
  1122.     while ((err = glGetError()) != GL_NO_ERROR) {
  1123.     fprintf(stderr, 
  1124.         "ERROR: %s: glGetError returned %s (expected GL_NO_ERROR)\n",
  1125.                 msg, gluErrorString(err));
  1126.     }
  1127. }
  1128. #endif
  1129. #endif /* defined on extensions (else part) */
  1130.